package com.wd.jetpack.api.network;

import android.util.Log;

import org.apache.log4j.Logger;

import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;

import okhttp3.Headers;
import okhttp3.Interceptor;
import okhttp3.MediaType;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.ResponseBody;
import okio.Buffer;
import okio.BufferedSource;

/**
 * Created by neil on 2017/4/18.
 */
public class LogInterceptor implements Interceptor {

    private static final String CPOS_HTTP = "LOG_HTTP";
    private static final Charset UTF8 = StandardCharsets.UTF_8;
    private static Logger logger = Logger.getLogger(CPOS_HTTP);

    @Override
    public Response intercept(Chain chain) throws IOException {
        long s = System.currentTimeMillis();
        Request request = chain.request();
        try {
            Response response = chain.proceed(request);
            long et = System.currentTimeMillis();
            String log = "";
            if (response.code() == 200) {
                log = String.format("%1$s %2$s %3$s %4$s", request.url().toString(), requestFormat(request), responseFormat(response), et - s);
            } else {
                log = String.format("%1$s %2$s %3$s %4$s", request.url().toString(), requestFormat(request), responseFormat(response), et - s);
            }
            Log.d(CPOS_HTTP, log);
            logger.info(log);
            return response;
        } catch (Throwable e) {
            long eT = System.currentTimeMillis();
            String log = String.format("%1$s %2$s %3$s %4$s", request.url().toString(), requestFormat(request), exceptionFormat(e), eT - s);
            Log.e(CPOS_HTTP, log);
            logger.info(log);
            throw e;
        }
    }

    private String requestFormat(Request request) throws IOException {

        boolean compressed = false;
        String curlCmd = "";
        Headers headers = request.headers();
        for (int i = 0, count = headers.size(); i < count; i++) {
            String name = headers.name(i);
            String value = headers.value(i);
            if ("Accept-Encoding".equalsIgnoreCase(name) && "gzip".equalsIgnoreCase(value)) {
                compressed = true;
            }
            curlCmd += " -H " + name + ": " + value + "\n";
        }
        curlCmd += "\n----------request----------\n";
        curlCmd += requestBody(request);
        curlCmd += ((compressed) ? " --compressed " : " ");

        logger.info(requestBody(request));
        return curlCmd;
    }

    private String requestBody(Request request) throws IOException {
        RequestBody requestBody = request.body();
        String curlCmd = "";
        if (requestBody != null) {
            Buffer buffer = new Buffer();
            requestBody.writeTo(buffer);
            Charset charset = UTF8;
            MediaType contentType = requestBody.contentType();
            if (contentType != null) {
                charset = contentType.charset(UTF8);
            }
            curlCmd += buffer.readString(charset).replace("\n", "\\n");
        }
        return curlCmd;
    }

    private String responseBody(Response response) throws IOException {
        ResponseBody responseBody = response.body();
        BufferedSource source = responseBody.source();
        source.request(Long.MAX_VALUE); // Buffer the entire body.
        Buffer buffer = source.buffer();

        Charset charset = UTF8;
        MediaType contentType = responseBody.contentType();
        if (contentType != null) {
            charset = contentType.charset(UTF8);
        }

        return buffer.clone().readString(charset);
    }

    private String responseFormat(Response response) throws IOException {
        String result = "\n----------response----------\n";
        result += String.format("%nStatusCode: %s", response.code());
        result += String.format("\n%s", responseBody(response));
        return result;
    }

    private String exceptionFormat(Throwable e) {
        String sb = "\n----------exception----------\n";
        Writer result = new StringWriter();
        PrintWriter printWriter = new PrintWriter(result);
        e.printStackTrace(printWriter);
        return sb + result.toString();
    }
}
